#include "swtimer.h"
#include <stddef.h>


/**********************************************************************
 * 简介：算法采用双向链表方式，使用硬件定时器作为时基，延伸出软件定时器。
 * 修改：添加临界,防止在开始和停止时进入ticks导致错误。
 * 版本：V1.0.7
 * 作者：xhli
 * 时间：20230407
 **********************************************************************/

SWTimerList_t SWTimerList;


void SWTimer_Init(void)
{
	SWTimerList.FirstNode.Next = (SWTimer_t*)(&SWTimerList.FirstNode);
	SWTimerList.FirstNode.Pre = (SWTimer_t*)(&SWTimerList.FirstNode);
	SWTimerList.SWTimerCounter = 0;
}

//相当于插入到链表尾部
void SWTimer_Start(SWTimer_t* SWTimerHandle,uint32_t DelayTicks,void (*TimerOut_CB)(void))
{
	static uint32_t Counter = 0;
	static SWTimer_t* SWTimerIndex = NULL;
	
	//进入临界状态
	SWTimer_EnterCritical();
	
	//若已经在链表中，则重新设置计数值。
	SWTimerHandle->TicksCounter = 0;
	SWTimerHandle->DelayTimes = DelayTicks;
	SWTimerHandle->timerout_cb = TimerOut_CB;

	//此节点已经在链表中了
	//若已经在链表中，则重新设置计数值。
	if((SWTimerHandle->ListOwner) == (&SWTimerList))
	{
		//退出临界状态
		SWTimer_ExitCritical();
		
		return;
	}
	
	//计算要插入链表的位置
	SWTimerIndex = (SWTimer_t*)(&SWTimerList.FirstNode)->Next;
	for(Counter = 0;Counter < SWTimerList.SWTimerCounter;Counter++)
	{
		if(SWTimerList.SWTimerCounter != 0)
		{
			if(SWTimerIndex->DelayTimes >= SWTimerIndex->TicksCounter)
			{
				if(SWTimerIndex->DelayTimes - SWTimerIndex->TicksCounter > SWTimerHandle->DelayTimes)
				{
					break;
				}
			}
			
			SWTimerIndex = SWTimerIndex->Next;
		}
	}

	//将其加入到链表中。
	SWTimerHandle->Next = SWTimerIndex;
	SWTimerHandle->Pre = SWTimerIndex->Pre;
	SWTimerIndex->Pre->Next = SWTimerHandle;
	SWTimerIndex->Pre = SWTimerHandle;
	//链表节点数加1
	SWTimerHandle->ListOwner = &SWTimerList;
	SWTimerList.SWTimerCounter++;
	
	//退出临界状态
	SWTimer_ExitCritical();
}


//判断定时器是否已经开始定时
//若已经开始返回1
//否则返回0
uint8_t SWTimer_ISStart(SWTimer_t* SWTimerHandle)
{
	//此节点已经在链表中了
	if((SWTimerHandle->ListOwner) == (&SWTimerList))
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

//	SWTimerHandle->timerout_cb = 0;
//	这三个变量不可以清除，否则无法索引
void SWTimer_Stop(SWTimer_t* SWTimerHandle)
{
	//此节点没有在链表中
	if((SWTimerHandle->ListOwner) != (&SWTimerList))
	{
		return;
	}
	
	//进入临界状态
	SWTimer_EnterCritical();
	
	//从链表中删除
	SWTimerHandle->Next->Pre = SWTimerHandle->Pre;
	SWTimerHandle->Pre->Next = SWTimerHandle->Next;
	SWTimerHandle->Next = 0;
    SWTimerHandle->Pre = 0;

	//表示此链表没有在链表中
	SWTimerHandle->ListOwner = 0;
	//链表节点计数器减一
	if(SWTimerList.SWTimerCounter != 0)
	{
		SWTimerList.SWTimerCounter--;
	}
	
	//退出临界状态
	SWTimer_ExitCritical();
}

void SWTimer_Tick(void)
{
	static uint32_t Counter = 0;
	static SWTimer_t* SWTimerIndex = NULL;
	static unsigned int ListNodeCounter = 0;
	
	SWTimerIndex = (SWTimer_t*)(&SWTimerList.FirstNode);
	
	ListNodeCounter = SWTimerList.SWTimerCounter;
	
	for(Counter = 0;Counter < ListNodeCounter;Counter++)
	{
		SWTimerIndex = SWTimerIndex->Next;
		
		SWTimerIndex->TicksCounter++;
	}
}


/**********************************************************
*
* 放在while循环中
*
**********************************************************/

void SWTimer_TimeOutProcess(void)
{
	static SWTimer_t* SWTimerIndex = NULL;

	while(SWTimerList.SWTimerCounter)
	{
		SWTimerIndex = ((SWTimer_t*)(&SWTimerList.FirstNode))->Next;

		if(SWTimerIndex->TicksCounter >= SWTimerIndex->DelayTimes)
		{
			//可以在此刻进入临界，关闭中断。
			SWTimer_Stop(SWTimerIndex);
			if(SWTimerIndex->timerout_cb != NULL)
			{
				SWTimerIndex->timerout_cb();
			}
		}
		else
		{
			break;
		}
	}
}


